
#include <cstdio>
#include <BScene>
#include "member_BScene.h"

using namespace BWE;

#define member					(*(member_BScene*)_ptr)
#define member_allocate()		_ptr = new member_BScene(this)
#define member_release()		delete (member_BScene*)_ptr

BScene::BScene()
{
	member_allocate();
}
BScene::~BScene()
{
	member_release();
}

void BScene::inserts(BNode* node)
{
	if (node && !member.nodes.contain(node))
	{
		if (BLight* light = dynamic_cast<BLight*>(node))
		{
			member.lights.append(light);
		}
		else if (BCamera* camera = dynamic_cast<BCamera*>(node))
		{
			member.cameras.append(camera);
		}
		member.nodes.append(node);
		member.connect(node, Signal_Fresh, &member_BScene::slotNodeFresh);
		member.connect(node, Signal_Dirty, &member_BScene::slotNodeDirty);
		member.dirtySpace = true;
		member.refresh = true;
	}
}
void BScene::inserts(BShape* shape)
{
	if (shape && !member.shapes.contain(shape))
	{
		member.shapes.append(shape);
		member.connect(shape, Signal_Fresh, &member_BScene::slotShapeFresh);
		member.connect(shape, Signal_Dirty, &member_BScene::slotShapeDirty);
		member.dirtySpace = true;
		member.refresh = true;
	}
}

bool BScene::removes(const BNode* node)
{
	if (node && member.nodes.contain(node))
	{
		if (const BLight* light = dynamic_cast<const BLight*>(node))
		{
			member.lights.remove(light);
		}
		else if (const BCamera* camera = dynamic_cast<const BCamera*>(node))
		{
			member.cameras.remove(camera);
		}
		member.disconnect((BNode*)node);
		member.nodes.remove(node);
		member.dirtySpace = true;
		member.refresh = true;
	}
	return false;
}
bool BScene::removes(const BShape* shape)
{
	if (shape && member.shapes.contain(shape))
	{
		member.disconnect((BShape*)shape);
		member.shapes.remove(shape);
		member.dirtySpace = true;
		member.refresh = true;
	}
	return true;
}

bool BScene::contains(const BNode* node) const
{
	return member.nodes.contain(node);
}
bool BScene::contains(const BShape* shape) const
{
	return member.shapes.contain(shape);
}

int BScene::shapeCount() const
{
	return member.shapes.size();
}
BShape* BScene::shape(int index) const
{
	return member.shapes(index);
}

int BScene::nodeCount() const
{
	return member.nodes.size();
}
BNode* BScene::node(int index) const
{
	BNodeHolder node = member.nodes(index);
	return node.ptr();
}
BNode* BScene::node(const BString& name) const
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		BNode* node = member.nodes[i];
		if (node->name() == name)
			return node;
	}
	return 0;
}

int BScene::lightCount() const
{
	return member.lights.size();
}
BLight* BScene::light(int index) const
{
	return member.lights(index);
}

int BScene::cameraCount() const
{
	return member.cameras.size();
}
BCamera* BScene::camera(int index) const
{
	return member.cameras(index);
}

void BScene::clearNodes()
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		member.disconnect(member.nodes[i]);
	}
	member.lights.clear();
	member.cameras.clear();
	member.nodes.clear();
	member.dirtySpace = true;
	member.refresh = true;
	emit(Signal_Dirty);
}
void BScene::clearShapes()
{
	for (int i = 0; i < member.shapes.size(); i++)
	{
		member.disconnect(member.shapes[i]);
	}
	member.shapes.clear();
	member.dirtySpace = true;
	member.refresh = true;
	emit(Signal_Dirty);
}
void BScene::clear()
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		member.disconnect(member.nodes[i]);
	}
	for (int i = 0; i < member.shapes.size(); i++)
	{
		member.disconnect(member.shapes[i]);
	}
	member.lights.clear();
	member.cameras.clear();
	member.nodes.clear();
	member.shapes.clear();
	member.dirtySpace = true;
	member.refresh = true;
	emit(Signal_Dirty);
}

const BSpace& BScene::space() const
{
	if (member.dirtySpace)
	{
		if (member.shapes.size())
		{
			member.space = member.shapes.first()->space();
			for (int i = 0; i < member.shapes.size(); i++)
			{
				BShape* shape = member.shapes[i];
				member.space.expand(shape->space());
			}
		}
		if (member.nodes.size())
		{
			if (member.space.empty())
				member.space.expand(member.nodes.first()->space());
			for (int i = 0; i < member.nodes.size(); i++)
			{
				BNode* node = member.nodes[i];
				member.space.expand(node->space());
			}
		}
		//printf("Rebuild Space : %s\n", this->name().cstr());
		member.dirtySpace = false;
	}
	return member.space;
}
